package com.ly.auth.config;

import com.ly.dal.datasource.RoutableDataSource;
import lombok.Data;
import org.apache.ibatis.session.AutoMappingBehavior;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * DAL组件配置
 * http://wiki.17usoft.com/pages/viewpage.action?pageId=28638230
 */
@Data
@Configuration
@MapperScan(basePackages = LargeScreenDataSourceConfig.MAPPER_PACKAGE, sqlSessionFactoryRef = "largeScreenSqlSessionFactory")
public class LargeScreenDataSourceConfig {

    /**
     * Mapper接口包路径
     */
    static final String MAPPER_PACKAGE = "com.ly.auth.mapper.large";

    /**
     * Mapper.xml文件相对路径
     */
    private static final String MAPPER_LOCATION = "classpath:mapper/large/*.xml";


    /**
     * 实体bean包路劲，用于注册mybatis xml中的别名
     */
    private static final String TYPE_ALIASES_PACKAGE = "com.ly.auth.entity";


    /**
     * 创建数据源实例
     */
    @Bean(name = "largeScreenDataSource", initMethod = "init", destroyMethod = "close")
    @ConfigurationProperties(prefix = "datasource.dal.large")
    public RoutableDataSource routableDataSource() {
        /*
        可以通过以下方式解密dal组件的数据库密码
        String projectId = "tcrobot.etv.user.server";
        StringEncrypt.decrypt("PW67IM25IIEMSCVW4G3L4ROM6CKNJOWTSDM7XWIBTUIZMJFOBJDQ", projectId);
         */
        RoutableDataSource routableDataSource = new RoutableDataSource();
        routableDataSource.setMaxActive(500);
        routableDataSource.setMinIdle(3);
        routableDataSource.setRemoveAbandoned(false);
        routableDataSource.setRemoveAbandonedTimeout(120);
        routableDataSource.setPhyTimeoutMillis(150000);

        Map<String, String> map = new HashMap<>();
        map.put("allowMultiQueries", "true");
        map.put("connectTimeout", "3000");
        map.put("socketTimeout", "5000");
        //将0000-00-00 00:00:00或者0000-00-00这样的日期/时间值转换为null
        map.put("zeroDateTimeBehavior","convertToNull");
        routableDataSource.setJdbcConnectionProperties(map);
        return routableDataSource;
    }

    /**
     * 创建数据源的事务管理
     */
    @Bean(name = "largeScreenTransactionManager")
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("largeScreenDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }


    /**
     * 创建Mybatis的连接会话工厂实例
     */
    @Bean(name = "largeScreenSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("largeScreenDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        // 设置数据源
        sessionFactoryBean.setDataSource(dataSource);

        //设置VFS（Virtual File System），SpringBootVFS是Spring Boot对MyBatis默认VFS类的一个改写，用于解决jar包无法扫描的问题。
        sessionFactoryBean.setVfs(SpringBootVFS.class);
        //注册指定包别名
        sessionFactoryBean.setTypeAliasesPackage(TYPE_ALIASES_PACKAGE);

        //注入mybatis-config.xml配置文件
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sessionFactoryBean.setConfigLocation(resolver.getResources("classpath:mybatis/mybatis-config.xml")[0]);

        // 设置Mapper.xml文件相对路径
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(LargeScreenDataSourceConfig.MAPPER_LOCATION));
        // 开启驼峰映射
        sessionFactoryBean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
        sessionFactoryBean.getObject().getConfiguration().setAutoMappingBehavior(AutoMappingBehavior.FULL);
        // 控制台打印sql
        sessionFactoryBean.getObject().getConfiguration().setLogImpl(org.apache.ibatis.logging.stdout.StdOutImpl.class);
        return sessionFactoryBean.getObject();
    }

    @Bean(name = "largeScreenSqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("largeScreenSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(name = "largeScreenServerJdbcTemplate")
    public JdbcTemplate jdbcTemplate(@Qualifier("largeScreenDataSource") DataSource largeScreenDataSource) {
        return new JdbcTemplate(largeScreenDataSource);
    }

}
